package edu.washington.ling.syntric.io;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import edu.washington.ling.syntric.struct.tree.Node;
import edu.washington.ling.syntric.struct.tree.Token;
import edu.washington.ling.syntric.struct.tree.Tree;
import edu.washington.ling.syntric.util.TreeUtils;
import edu.washington.ling.syntric.util.Utils;


public class TreeWriterSSF extends TreeWriter {

	
	private String getFeatureString(Node n) {
		String featStr = null;
		ArrayList<String> fvStrs = new ArrayList<String>();
		for (String feat: n.getFeatures()) {
			if (!n.isDerrived(feat)) {
				fvStrs.add(String.format("%s=\"%s\"", feat, n.getValue(feat)));
			}
		}
		if(fvStrs.size() > 0) {
			featStr = Utils.join(fvStrs, " ");
		}
		return featStr;
	}
	private String getLineForToken(Token t, String index){
		String word = t.getWord();
		String line = String.format("%s\t%s", index, word);
		String tag = null;
		if ((tag = t.getTag()) != null) {
			line = String.format("%s\t%s", line, tag);
		}
		String featStr = null;
		if ((featStr = getFeatureString(t)) != null) {
			line = String.format("%s\t<fs %s>", line, featStr);
		}
		return line;
	}
	private String getLineForNode(Node n, String index){
		String label = n.getLabel();
		String line = String.format("%s\t((\t%s", index, label);
		String featStr = null;
		if ((featStr = getFeatureString(n)) != null) {
			line = String.format("%s\t<fs %s>", line, featStr);
		}
		// TODO: ps heads should be normal features (i.e. listed in fs)
		/*
		String headWordStr = Utils.join(n.getHeadWords(), "|");
		line = String.format("%s\t%s", line, headWordStr);
		*/
		return line;
	}
	private List<String> getPSTreeLines(Node n) {
		return getPSTreeLines(n, "1");
	}
	private List<String> getPSTreeLines(Node n, String index){
		ArrayList<String> lines = new ArrayList<String>();
		if (n instanceof Token) {
			lines.add(getLineForToken((Token) n, index));
		}
		else {
			lines.add(getLineForNode(n, index));
			int count = 1;
			for (Node child: n.getPSChildren()) {
				String childIndex = String.format("%s.%d", index, count);
				lines.addAll(getPSTreeLines(child, childIndex));
				count++;
			}
			String endBranchLine = "\t))";
			lines.add(endBranchLine);
		}
		return lines;
	}
	private List<String> getTokenLines(Tree tree){
		List<String> lines = new LinkedList<String>();
		int count = 1;
		for (Token t: tree.getTokenList()) {
			String index = Integer.toString(count);
			lines.add(getLineForToken(t, index));
			count++;
		}
		return lines;
	}
	private List<String> getTreeLines(Tree tree) {
		TreeUtils.writeDSLinksAsFeatures(tree);
		TreeUtils.writePBLinksAsFeatures(tree);
		List<String> lines;
		if (tree.hasPSRoot()) {
			lines = getPSTreeLines(tree.getPSRoot());
		} else {
			lines = getTokenLines(tree);
		}
		return lines;
	}
	
	@Override
	public TreeRepresentation writeTree(Tree tree) {
		List<String> lines = getTreeLines(tree);
		return new TreeRepresentation(lines, tree.getLayer(), "ssf");
	}

}
